home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-05 | 11.9 KB | 273 lines | [TEXT/PJMM] |
- Program PictConvert;
-
- Uses
- AppleTalk, Aliases, Processes, PPCToolBox, EPPC, Notification, AppleEvents;
-
- Var
- TargetApp, TargetDir, LogFile: FSSpec;
- Err: OSErr;
- HomeVolName, TargVolName: Str255;
- HomeVolNamePtr, TargVolNamePtr: StringPtr;
- HomeVRefNum, TargVRefNum, x, LogRef: Integer;
- HomeDirID, TempFreeBytes: LongInt;
- TargetPB: CInfoPBRec;
- TargetPBPtr: CInfoPBPtr;
- TargIsFolder, WasAliased, GotAppDied: Boolean;
- TheEvent: EventRecord;
- TheKeys: KeyMap;
-
-
-
- Function DoAppDiedEvent (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
- Begin
- GotAppDied := True;
- DoAppDiedEvent := NoErr;
- End;
-
- Function DoAEOpen (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
- Begin
- DoAEOpen := NoErr;
- End;
-
- Function DoAEOpenDoc (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
- Begin
- DoAEOpenDoc := errAEEventNotHandled;
- End;
-
- Function DoAEPrintDoc (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
- Begin
- DoAEPrintDoc := errAEEventNotHandled;
- End;
-
- Function DoAEQuit (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
- Begin
- DoAEQuit := errAEEventNotHandled;
- End;
- {These are all AppleEvent handler routines -- the only one we need }
- {is the DoAppDied event. The other four are the 'required' AppleEvents}
-
-
- Procedure ConvertFile (Targ: FSSpec);
- Var
- theAEvent: AppleEvent;
- tempDesc, launchDesc, docDesc: AEDesc;
- docDescList: AEDescList;
- tempPSN, TargetPSN: ProcessSerialNumber;
- docAlias: AliasHandle;
- launchParams: LaunchParamBlockRec;
- appParams: AppParametersPtr;
- Qel: EvQElPtr;
- x: LongInt;
- Nix: Boolean;
- WriteData: Array[1..33] Of Byte;
-
- Begin
- tempDesc.dataHandle := Nil;
- theAEvent.dataHandle := Nil;
- docDescList.dataHandle := Nil;
- docAlias := Nil;
- tempPSN.highLongOfPSN := 0;
- tempPSN.lowLongOfPSN := kCurrentProcess;
- Err := AECreateDesc(typeProcessSerialNumber, @tempPSN, SizeOf(ProcessSerialNumber), tempDesc);
- Err := AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, tempDesc, kAutoGenerateReturnID, kAnyTransactionID, theAEvent);
- Err := AEDisposeDesc(tempDesc);
- Err := AECreateList(Nil, 0, False, docDescList);
- Err := NewAlias(Nil, Targ, docAlias);
- docDesc.descriptorType := typeAlias;
- docDesc.dataHandle := Handle(docAlias);
- Err := AEPutDesc(docDescList, 0, docDesc);
- DisposHandle(Handle(docAlias));
- docAlias := Nil;
- Err := AEPutParamDesc(theAEvent, keyDirectObject, docDescList);
- Err := AEDisposeDesc(docDescList);
- Err := AECoerceDesc(theAEvent, typeAppParameters, launchDesc);
- Err := AEDisposeDesc(theAEvent);
- HLock(Handle(launchDesc.dataHandle));
- appParams := AppParametersPtr(launchDesc.dataHandle^);
- With launchParams Do
- Begin
- launchBlockID := extendedBlock;
- launchEPBLength := extendedBlockLen;
- launchfileFlags := 0;
- launchControlFlags := launchContinue + launchNoFileFlags + launchUseMinimum + launchAllow24Bit;
- launchAppSpec := @TargetApp;
- launchAppParameters := appParams;
- End;
- Err := LaunchApplication(@launchParams);
- HUnlock(Handle(launchDesc.dataHandle));
- Err := AEDisposeDesc(launchDesc);
- {The credit for the above code goes to Forrest Tanaka and Pete Helm. (Especially Pete,}
- {for making a Pascal conversion of Forrest's code) The code was taken basically }
- {verbatim from the "ProcDoggie" code found on the Developer's CD. Don't ask me >how< }
- {it works, it just does. You go in with a file specification, and these wonderful }
- {AppleEvent Manager calls do something with it so you can specify a document for the }
- {Process Manager's 'LaunchApplication' call so the launched application can open the }
- {file! Pretty neat, huh? Especially neat since the Process manager chapter of IM: }
- {Processes mentions that it's possible, but doesn't give any samples. This is a very }
- {simple way of specifying one file for opening that some people might find more }
- {digestable than the ProcDoggie code, which covers a much wider and complexly }
- {structured example of the LaunchApplication call. (and a whole ton of other stuff!) }
-
- TargetPSN := launchParams.launchProcessSN;
- {we need this to keep an eye on our launched app. read on...}
-
- Repeat
- Nix := WaitNextEvent(EveryEvent, TheEvent, 200, Nil);
- Err := GetFrontProcess(tempPSN);
- Err := SameProcess(TargetPSN, tempPSN, Nix);
- GetKeys(TheKeys)
- Until ((Nix) Or (TheKeys[56]));
- {Translation: hang out and don't do anything until we see that our launched app has }
- {made it to the foreground. Otherwise it (the app) won't get the events we're about }
- {to send. }
-
- If (Not TheKeys[56]) Then
- Begin
- Err := PPostEvent(3, Ord4('s'), Qel); {Post a keydown for the letter 's' using }
- Qel^.evtQModifiers := 384; {PPostEvent so we can go back into the event }
- x := 0; {and make it look like the Command key was used}
- With Targ Do {Efectively giving the forground app a 'Cmd-S' }
- Repeat
- x := x + 1;
- Err := PostEvent(3, Ord4(name[x])); {Walk through the file name "typing" each letter}
- Until (name[x] = '.'); {up to the period. }
- Err := PostEvent(3, Ord4('g')); {Gimme a 'g'! }
- Err := PostEvent(3, Ord4('i')); {Gimme an 'i'!}
- Err := PostEvent(3, Ord4('f')); {Gimme an 'f'!}
- x := TickCount + 300;
- While (x > TickCount) Do {Wait a few seconds for the app's}
- Nix := WaitNextEvent(EveryEvent, TheEvent, 0, Nil); {dialog to catch up if need be. }
- Err := PostEvent(3, 3); {Post 'Enter' key. (keycode 3) }
- Err := PPostEvent(3, Ord4('q'), Qel);
- Qel^.evtQModifiers := 384; {Post a 'Cmd-Q' using the same method as before }
- {so app quits after finishing it's save command }
-
- GotAppDied := False;
- Repeat
- Nix := WaitNextEvent(EveryEvent, TheEvent, 2000, Nil);
- If (TheEvent.what = kHighLevelEvent) Then
- Err := AEProcessAppleEvent(TheEvent);
- GetKeys(TheKeys);
- Until ((GotAppDied) Or (TheKeys[56]));
- {Translation: hang out and do nothing until we recieve the 'Child Died' or 'App Died' event,}
- {telling us that our previously launched application has quit. }
-
- If GotAppDied Then {We assume the app died after completing it's task, so}
- Err := FSpDelete(Targ); {we go ahead and delete the original file }
-
- Err := FlushVol(TargVolNamePtr, TargVRefNum); {Update the volume after having a new file}
- {created and another deleted. }
- For x := 1 To Length(Targ.Name) Do
- WriteData[x] := Byte(Targ.Name[x]);
- x := Length(Targ.Name) + 1;
- WriteData[x] := 13;
- Err := FSWrite(LogRef, x, @WriteData); {Write name of converted file to our log file}
- End;
- End;
-
-
- Procedure SearchDir (SVRefNum: Integer; SDirID: LongInt);
- Var
- GetCatErr: OSErr;
- x: Integer;
- SearchPB: CInfoPBRec;
- SearchPBPtr: CInfoPBPtr;
- SearchName: Str255;
- SearchNamePtr: StringPtr;
- SearchNeg: Boolean;
- TargetFile: FSSpec;
-
- Begin
- SearchNamePtr := @SearchName;
- SearchPBPtr := @SearchPB;
- Repeat
- SearchNeg := True; {Assume we won't find a target file}
- x := 1;
- With SearchPB Do {Starting with first item in directory, (x) }
- Begin {Use PBGetCatInfo to see if item is a folder}
- ioCompletion := Nil; {or file. If it's a folder, call SearchDir }
- ioNamePtr := SearchNamePtr; {recursively with folder info. If it's a }
- ioVRefNum := SVRefNum; {file, see if it looks like a Pict, and if }
- ioFDirIndex := x; {so, call our conversion routine }
- ioDirID := SDirID;
- End;
- GetCatErr := PBGetCatInfo(SearchPBPtr, False);
- If (GetCatErr = NoErr) Then
- Repeat
- If (BitTst(@SearchPB.ioFlAttrib, 3)) Then
- Begin {dir}
- SearchDir(SearchPB.ioVRefNum, SearchPB.ioDrDirID);
- End
- Else
- Begin {file}
- If (pos('.pict', SearchName) <> 0) Or (pos('.PICT', SearchName) <> 0) Then
- Begin
- SearchNeg := False; {We found a target. Reset search for this directory}
- GetCatErr := fnfErr;
- Err := FSMakeFSSpec(SearchPB.ioVRefNum, SearchPB.ioFlParID, SearchName, TargetFile);
- ConvertFile(TargetFile);
- End;
- End;
- x := x + 1;
- SearchPB.ioFDirIndex := x;
- SearchPB.ioDirID := SDirID;
- If (SearchNeg) Then {We don't want to call PBGetCatInfo if }
- GetCatErr := PBGetCatInfo(SearchPBPtr, False); {we processed a target. dump out of }
- GetKeys(TheKeys); {loop to start over with this directory}
- Until ((GetCatErr = fnfErr) Or (TheKeys[56]));
- Until ((SearchNeg) Or (TheKeys[56])); {Search Directory until we get to the end}
- End; {or we find a target. If we got to the }
- {end, exit routine. If we got (and }
- {processed) a target, start over }
- Begin
- HomeVolNamePtr := @HomeVolName;
- TargetPBPtr := @TargetPB;
- TargVolNamePtr := @TargVolName;
- {Create File Spec records}
- Err := HGetVol(HomeVolNamePtr, HomeVRefNum, HomeDirID); {for our app to be }
- Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Target App', TargetApp); {launched, directory to }
- Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Target Dir', TargetDir); {scan for files, and our }
- Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Log File', LogFile); {file for logging targets}
-
- Err := ResolveAliasFile(TargetDir, True, TargIsFolder, WasAliased); {Make sure Target Dir }
- {really IS a directory }
- {and...}
- If TargIsFolder Then {don't continue otherwise}
- Begin
- Err := AEInstallEventHandler(kCoreEventClass, kAEApplicationDied, @DoAppDiedEvent, 0, False);
- Err := AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, @DoAEOpen, 0, False);
- Err := AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, @DoAEOpenDoc, 0, False);
- Err := AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, @DoAEPrintDoc, 0, False);
- Err := AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, @DoAEQuit, 0, False);
- {Install our event handlers for the required events (that we don't use anyway)}
- {and the 'App Died' event. }
-
- x := -1;
- Repeat
- Err := GetVInfo(x, TargVolNamePtr, TargVRefNum, TempFreeBytes);
- x := x - 1;
- Until (TargVRefNum = TargetDir.VRefNum);
- {Get volume number and name for the target directory's volume so we can do FlushVol's for it}
- {later on. Wish we could just use the volume refrence number, but oh well... }
-
- Err := FSpDelete(LogFile);
- Err := FSpCreate(LogFile, 'ttxt', 'TEXT', -1); {Create our file for logging converted files}
- Err := FSpOpenDF(LogFile, fsWrPerm, LogRef); {obliterating any existing one. }
-
- If (Err = NoErr) Then
- Begin
- With TargetPB Do
- Begin
- ioCompletion := Nil;
- ioNamePtr := @TargetDir.Name;
- ioVRefNum := TargetDir.VRefNum;
- ioFDirIndex := 0;
- ioDrDirID := TargetDir.ParID;
- End; {Set things rolling by calling SearchDir}
- Err := PBGetCatInfo(TargetPBPtr, False); {with the info on Target Dir. }
- SearchDir(TargetPB.ioVRefNum, TargetPB.ioDrDirID);
- Err := FSClose(LogRef);
- Err := FlushVol(HomeVolNamePtr, HomeVRefNum); {when done, close and flush our log file}
- End;
- End;
- End.